package com.atguigu.gulimall.ware.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.exception.NoStockException;
import com.atguigu.common.to.mq.StockDetailTo;
import com.atguigu.common.to.mq.StockLockedTo;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.ware.entity.WareOrderTaskDetailEntity;
import com.atguigu.gulimall.ware.entity.WareOrderTaskEntity;
import com.atguigu.gulimall.ware.entity.vo.SkuHasStockVo;
import com.atguigu.gulimall.ware.feign.OrderFeignClient;
import com.atguigu.gulimall.ware.service.WareOrderTaskDetailService;
import com.atguigu.gulimall.ware.service.WareOrderTaskService;
import com.atguigu.gulimall.ware.vo.OrderItemVo;
import com.atguigu.gulimall.ware.vo.OrderVo;
import com.atguigu.gulimall.ware.vo.WareSkuLockVo;
import com.rabbitmq.client.Channel;
import com.sun.org.apache.bcel.internal.generic.ARRAYLENGTH;
import lombok.Data;
import org.apache.commons.lang.enums.Enum;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.ware.dao.WareSkuDao;
import com.atguigu.gulimall.ware.entity.WareSkuEntity;
import com.atguigu.gulimall.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {
    @Autowired
    WareSkuDao wareSkuDao;
    @Autowired
    WareOrderTaskDetailService wareOrderTaskDetailService;
    @Autowired
    WareOrderTaskService wareOrderTaskService;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Value("${myRabbitmq.MQConfig.eventExchange}")
    private String eventExchange;
    @Value("${myRabbitmq.MQConfig.routingKey}")
    private String routingKey;
    @Autowired
    OrderFeignClient orderFeignClient;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                new QueryWrapper<WareSkuEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds) {
        List<SkuHasStockVo> list = baseMapper.getSkuHasStock(skuIds);
        return list;
    }

    //库存需要重新解锁的场景有：1，订单过期没有支付或用户手动取消，2，订单下单成功，其他业务失败导致订单回滚
    @Transactional(rollbackFor = NoStockException.class)
    @Override
    public Boolean orderLockStock(WareSkuLockVo wareSkuLockVo) {
        List<OrderItemVo> locks = wareSkuLockVo.getLocks();

        WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();
        wareOrderTaskEntity.setOrderSn(wareSkuLockVo.getOrderSn());
        wareOrderTaskService.save(wareOrderTaskEntity);

        //1.查询sku在哪个仓库有库存
        List<WareHasStock> hasStocks = locks.stream().map(item -> {
            WareHasStock wareHasStock = new WareHasStock();
            Long skuId = item.getSkuId();
            wareHasStock.setSkuId(skuId);
            wareHasStock.setNum(item.getCount());
            List<Long> wareIds = wareSkuDao.listWareIdHasStock(skuId);
            wareHasStock.setWareIds(wareIds);
            return wareHasStock;
        }).collect(Collectors.toList());

        //2.锁定库存
        if (!CollectionUtils.isEmpty(hasStocks)) {
            for (WareHasStock hasStock : hasStocks) {
                Boolean skuLocked = false;
                Long skuId = hasStock.getSkuId();
                Integer num = hasStock.getNum();
                List<Long> wareIds = hasStock.getWareIds();
                if (CollectionUtils.isEmpty(wareIds)) {
                    throw new NoStockException(skuId);
                }
                for (Long wareId : wareIds) {
                    //成功返回1，否则0
                    Long count = wareSkuDao.lockStock(skuId, wareId, num);
                    if (count == 1) {
                        skuLocked = true;

                        WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
                        wareOrderTaskDetailEntity.setSkuId(skuId);
                        wareOrderTaskDetailEntity.setLockStatus(1);
                        wareOrderTaskDetailEntity.setWareId(wareId);
                        wareOrderTaskDetailEntity.setSkuNum(num);
                        wareOrderTaskDetailEntity.setTaskId(wareOrderTaskDetailEntity.getId());
                        wareOrderTaskDetailService.save(wareOrderTaskDetailEntity);

                        StockLockedTo stockLockedTo = new StockLockedTo();
                        stockLockedTo.setTaskId(wareOrderTaskEntity.getId());
                        StockDetailTo stockDetailTo = new StockDetailTo();
                        BeanUtils.copyProperties(wareOrderTaskDetailEntity, stockDetailTo);
                        stockLockedTo.setStockDetailTo(stockDetailTo);
                        //告诉mq锁定成功
                        rabbitTemplate.convertAndSend(eventExchange, routingKey, stockLockedTo);
                        break;//锁成功后不锁其他仓库了
                    } else {
                        //当前仓库锁库存失败，重试下一个仓库
                    }
                }
                if (!skuLocked) {//当前商品没有锁定成功，则其他商品不用继续锁了
                    throw new NoStockException(skuId);
                }

            }
        }

        return true;
    }

    @Override
    public void releaseLockedStock(StockLockedTo to) {
        StockDetailTo stockDetailTo = to.getStockDetailTo();
        Long detailId = stockDetailTo.getId();

        WareOrderTaskDetailEntity taskDetailEntity = wareOrderTaskDetailService.getById(detailId);
        if (taskDetailEntity != null) {
            //库存正常锁定，但是无法保证订单其他业务正常，需要看订单状态：1，没有查到订单，需要解锁库存 2，订单已取消，需要解锁，未取消，不解锁
            Long taskId = to.getTaskId();
            WareOrderTaskEntity taskEntity = wareOrderTaskService.getById(taskId);
            String orderSn = taskEntity.getOrderSn();
            R r = orderFeignClient.getOrderStatus(orderSn);
            if (r.getCode() == 0) {
                OrderVo data = r.getData(new TypeReference<OrderVo>() {
                });
                //订单状态【0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单】
                if (data == null || data.getStatus() == 4) {
                    //解锁库存
                    //1-已锁定  2-已解锁  3-扣减
                    if(taskDetailEntity.getLockStatus()==1){
                        releaseLockedStock(stockDetailTo);
                    }
                }
            } else {
                throw new RuntimeException("远程调用异常");
            }
        }
    }

    @Data
    class WareHasStock {
        private Long skuId;
        private Integer num;
        private List<Long> wareIds;
    }


    public void releaseLockedStock(StockDetailTo stockDetailTo) {
        baseMapper.releaseLockedStock(stockDetailTo);
        //修改工作单的锁定状态
        WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
        wareOrderTaskDetailEntity.setId(stockDetailTo.getId());
        wareOrderTaskDetailEntity.setLockStatus(2);
        wareOrderTaskDetailService.updateById(wareOrderTaskDetailEntity);
    }

}